/*
 * Copyright (c) novafaen design 2009 
 */
package tentaflykt.editor.xml;

/**
 * XML Formatter class, used to parse data into a correctly
 * formatted string.<br>
 * XML version 1.0, Character coding UTF-8
 * @author Kristoffer Nilsson
 */
public class XMLFormatter {
  private final String header = "<?xml version='1.0' encoding='UTF-8'?>\n";
  private StringBuilder xmlBuffer = null;
  
  /**
   * Default constructor, creates a <code>XMLFormatter</code> instance.<br>
   */
  public XMLFormatter() {
    xmlBuffer = new StringBuilder();

    // xml header
    xmlBuffer.append(header);
  }
  
  /**
   * Constructor, creates a <code>XMLFormatter</code> instance with
   * a DTD tag.
   * @param rootElement Root element
   * @param dtdFile DTD file name
   */
  public XMLFormatter(String rootElement, String dtdFile) {
    xmlBuffer = new StringBuilder();
    
    // xml header
    xmlBuffer.append(header);
    
    // dtd file
    xmlBuffer.append("<!DOCTYPE " + rootElement + " SYSTEM \"" + dtdFile + "\">\n");
  }
  
  /**
   * Constructor, creates a <code>XMLFormatter</code> instance with
   * a DTD tag and a comment.
   * @param topComment Top Comment
   * @param rootElement Root element
   * @param dtdFile DTD file name
   */
  public XMLFormatter(String topComment, String rootElement, String dtdFile) {
    xmlBuffer = new StringBuilder();
    
    // xml header
    xmlBuffer.append(header);
    
    // comment
    xmlBuffer.append("\n<!-- " + topComment + " -->\n\n");
    
    // dtd file
    xmlBuffer.append("<!DOCTYPE " + rootElement + " SYSTEM \"" + dtdFile + "\">\n");
  }
  
  /**
   * Appends element start-tag; &lt;<i>eName</i>&gt;
   * @param elementName Element name
   * @param tabCount Tab count
   */
  public void startElement(String elementName, int tabCount) {
    // add tabs
    for (int i = 0; i < tabCount; i++) {
      xmlBuffer.append("\t");
    }
    xmlBuffer.append("<" + elementName + ">\n");
  }
  
  /**
   * Append element end-tag; &lt;/<i>eName</i>&gt;
   * @param elementName Element name
   * @param tabCount Tab count
   */
  public void endElement(String elementName, int tabCount) {
    // add tabs
    for (int i = 0; i < tabCount; i++) {
      xmlBuffer.append("\t");
    }
    xmlBuffer.append("</" + elementName + ">\n");
  }
  
  /**
   * Append element end-tag; &lt;/<i>eName</i>&gt;
   * @param eName Element name
   */
  public void endElement(String eName) {
    xmlBuffer.append("</" + eName + ">\n");
  }

  /**
   * Append element start-tag; &lt;<i>eName attribute #1=</i>"<i>value #1</i>" ... 
   * <i>attribute #n</i>="<i>value #n</i>"&gt;
   * @param elementName Element name
   * @param attrs Attributes
   * @param tabCount Tab count
   */
  public void startElement(String elementName, XMLAttribute[] attrs, int tabCount) {
    // add tabs
    for (int i = 0; i < tabCount; i++) {
      xmlBuffer.append("\t");
    }
    xmlBuffer.append("<" + elementName);
    
    for (XMLAttribute attr : attrs) {
      xmlBuffer.append(" " + attr.getKey() + "=\"" + attr.getValue() + "\"");
    }
    
    xmlBuffer.append(">");
  }
  
  /**
   * Append element start-tag; &lt;<i>eName attribute #1=</i>"<i>value #1</i>" ... 
   * <i>attribute #n</i>="<i>value #n</i>"&gt;
   * @param elementName Element name
   * @param attr Attribute
   * @param tabCount Tab count
   */
  public void startElement(String elementName, XMLAttribute attr, int tabCount) {
    // add tabs
    for (int i = 0; i < tabCount; i++) {
      xmlBuffer.append("\t");
    }
    xmlBuffer.append("<" + elementName + " " + attr.getKey() + "=\"" + attr.getValue() + "\">");
  }
  
  /**
   * Append element start-tag, that self ends; 
   * &lt;<i>eName attribute #1=</i>"<i>value #1</i>" ... 
   * <i>attribute #n</i>="<i>value #n</i>"/&gt;
   * @param elementName Element name
   * @param attrs Attributes
   * @param tabCount Tab count
   */
  public void startEndElement(String elementName, XMLAttribute[] attrs, int tabCount) {
    // add tabs
    for (int i = 0; i < tabCount; i++) {
      xmlBuffer.append("\t");
    }
    xmlBuffer.append("<" + elementName);
    
    for (XMLAttribute attr : attrs) {
      xmlBuffer.append(" " + attr.getKey() + "=\"" + attr.getValue() + "\"");
    }
    
    xmlBuffer.append("/>");
  }
  
  /**
   * Append content, will be translated to <code>String</code> with the
   * <code>toString()</code> function.
   * @param content The content
   */
  public void content(Object content) {
    xmlBuffer.append(content.toString());
  }
  
  /**
   * Append a comment; &lt!-- <i>comment</i> --&gt
   * @param comment
   */
  public void comment(String comment) {
    // TODO: go trough string and indent
    //   also, new comment with tabCount
    xmlBuffer.append("<!-- " + comment + " -->\n");
  }
  
  /**
   * Returns the formatted XML string.
   * @return XML string
   */
  public String getXML() {
    return xmlBuffer.toString();
  }
}
